package co.fitstart.admin.web.controller.course;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.demo2do.core.BusinessException;
import com.demo2do.core.support.Page;
import com.demo2do.core.support.Result;
import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.core.utils.DateFormatUtils;
import com.demo2do.core.utils.JsonUtils;
import com.demo2do.core.web.utils.WebUtils;
import co.fitstart.admin.cache.accessor.PersistentAccessor;
import co.fitstart.admin.entity.content.RoundSearch;
import co.fitstart.admin.entity.security.Login;
import co.fitstart.admin.service.BasicInformationService;
import co.fitstart.admin.service.CoachService;
import co.fitstart.admin.service.CourseRoundService;
import co.fitstart.admin.service.GroupService;
import co.fitstart.admin.service.GroupTemplateService;
import co.fitstart.admin.service.InbodyRecordService;
import co.fitstart.admin.service.OfflineRoundService;
import co.fitstart.admin.service.PrincipalService;
import co.fitstart.admin.service.ResultReportService;
import co.fitstart.admin.service.SiteService;
import co.fitstart.admin.service.StudentService;
import co.fitstart.admin.web.interceptor.MenuSetting;
import co.fitstart.admin.web.resolver.Secure;
import co.fitstart.entity.course.CourseType;
import co.fitstart.entity.course.CourseUnit;
import co.fitstart.entity.course.round.CourseRound;
import co.fitstart.entity.course.round.CourseRoundResult;
import co.fitstart.entity.course.round.Goal;
import co.fitstart.entity.course.round.RoundStatus;
import co.fitstart.entity.courseware.CoursewareTag;
import co.fitstart.entity.courseware.assessment.BasicData;
import co.fitstart.entity.courseware.assessment.PostureJoint;
import co.fitstart.entity.courseware.assessment.StudentHabit;
import co.fitstart.entity.courseware.dietary.Dietary;
import co.fitstart.entity.courseware.exercise.Exercise;
import co.fitstart.entity.courseware.fitnessgroup.FitnessGroup;
import co.fitstart.entity.principal.Principal;
import co.fitstart.entity.site.Site;
import co.fitstart.entity.user.StudentTargetData;
import co.fitstart.entity.user.basic.BodyDataTarget;
import co.fitstart.entity.user.bwh.BwhRecord;
import co.fitstart.entity.user.inbody.InbodyRecord;

/**
 * 
 * @author lidan
 *
 */
@Controller
@RequestMapping("/special-rounds")
@MenuSetting("menu-course")
public class SpecialRoundController {
    
    private static final Logger logger = LoggerFactory.getLogger(SpecialRoundController.class);
    
    @Autowired
    private OfflineRoundService offlineRoundService;
    
    @Autowired
    private CourseRoundService courseRoundService;
    
    @Autowired
    private PrincipalService principalService;
    
    @Autowired
    private InbodyRecordService inbodyRecordService;
    
    @Autowired
    private GroupTemplateService groupTemplateService;
    
    @Autowired
    private PersistentAccessor persistentAccessor;
    
    @Autowired
    private StudentService studentService;
    
    @Autowired
    private BasicInformationService basicInformationService;
    
    @Autowired
    private GroupService groupService;
    
    @Autowired
    private ResultReportService resultReportService;
    
    @Autowired
    private SiteService siteService;
    
    @Autowired
    private CoachService coachService;
    
    /**
     * 
     * @param login
     * @param status
     * @param experience
     * @param siteId
     * @param page
     * @param request
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.GET)
    @MenuSetting("submenu-special-course-arrange")
    public ModelAndView list(@Secure Login login,
                             @RequestParam(name = "status", required = false, defaultValue = "prepare") String status,
                             @RequestParam(name = "experience", required = false, defaultValue = "0") boolean experience,
                             @RequestParam(name = "give", required = false, defaultValue = "0") boolean give,
                             @RequestParam(name = "site", required = false) Long siteId,
                             Page page,
                             HttpServletRequest request){

        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-list");
        modelAndView.addObject("pagetype", "special");
        Site site = null;
        if(!login.hasSite() && siteId != null) {
            site = siteService.load(siteId);
        }else if (login.hasSite()){
            site = login.getSite();
        }
        
        List<CourseRound> courseRounds = new ArrayList<>();
        
        if(site == null && (login.isAreaManager() || login.isAreaServer())) {
            Principal principal = principalService.load(Principal.class, login.getId());
            
            List<Site> sites = siteService.listSite(principal);
            
            if(!sites.isEmpty()) {
                courseRounds = courseRoundService.list(sites, RoundStatus.aliasOf(status), CourseType.SPECIAL, experience, give, page);
            }
        } else {
            courseRounds = courseRoundService.list(site, RoundStatus.aliasOf(status), CourseType.SPECIAL, experience, give, page);
        }
        
        modelAndView.addObject("courseRounds", courseRounds);
        
        modelAndView.addObject("status", status);
        modelAndView.addObject("experience", experience);
        modelAndView.addObject("give", give);
        modelAndView.addObject("site", site == null ? null : site.getId());

        modelAndView.addObject("page", page);
        
        modelAndView.addObject("refer", "list");
        modelAndView.addObject("queryString", WebUtils.extractQueryString(request, "page"));
        return modelAndView;
    }
    
    /**
     * 
     * @param status
     * @param experience
     * @return
     */
    @RequestMapping(value = "/search", method = RequestMethod.GET)
    public ModelAndView search(@RequestParam("status") String status,
                               @RequestParam("experience") boolean experience,
                               @RequestParam("give") boolean give,
                               @RequestParam(name = "site", required = false) Long site) {
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-search");
        modelAndView.addObject("pagetype", "special");
        modelAndView.addObject("status", status);
        modelAndView.addObject("experience", experience);
        modelAndView.addObject("give", give);
        modelAndView.addObject("site", site);
        modelAndView.addObject("courseType", "special");
        
        return modelAndView;
    }
    
    /**
     * 
     * @param roundSearch
     * @param status
     * @param experience
     * @param page
     * @param request
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.GET, params = "filter")
    @MenuSetting("submenu-special-course-arrange")
    public ModelAndView onSearch(@Secure Login login,
                                 RoundSearch roundSearch,
                                 @RequestParam("status") String status,
                                 @RequestParam("experience") boolean experience,
                                 @RequestParam("give") boolean give,
                                 Page page,
                                 HttpServletRequest request) {
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-list");
        modelAndView.addObject("pagetype", "special");
        if(login.isAreaManager() || login.isAreaServer()) {
            Principal principal = principalService.load(Principal.class, login.getId());
            
            List<Site> sites = siteService.listSite(principal);
            
            roundSearch.setSites(sites);
        }
        
        if(roundSearch.getSites() == null || !roundSearch.getSites().isEmpty()) {
            List<CourseRound> courseRounds = offlineRoundService.search(roundSearch, page);
            
            modelAndView.addObject("courseRounds", courseRounds);
        }
        
        modelAndView.addObject("status", status);
        modelAndView.addObject("experience", experience);
        modelAndView.addObject("give", give);
        modelAndView.addObject("site", roundSearch.getSite());

        modelAndView.addObject("page", page);
        
        modelAndView.addObject("refer", "search");
        modelAndView.addObject("queryString", WebUtils.extractQueryString(request, "page"));
        modelAndView.addObject("queryPattern", WebUtils.extractQueryString(request, "status","experience","give","page","site"));
        return modelAndView;
    }
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}", method = RequestMethod.GET)
    @MenuSetting("submenu-special-course-arrange")
    public ModelAndView view(@PathVariable("courseRoundId") Long courseRoundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-view");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        modelAndView.addObject("courseRound", courseRound);       
        
        CourseRoundResult resultReport = resultReportService.loadResultReport(courseRound);
        modelAndView.addObject("resultReport", resultReport);
        
        return modelAndView;
    }
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/physical-data", method = RequestMethod.GET)
    @MenuSetting("submenu-special-course-arrange")
    public ModelAndView physicalDataview(@PathVariable("courseRoundId") Long courseRoundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-physical-data-view");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        modelAndView.addObject("courseRound", courseRound);
        
        logger.info("# get courseRoundID [{}]  courseRound [{}]",courseRoundId,courseRound);
        List<InbodyRecord> inbodyRecords = inbodyRecordService.listInbodyRecoreds(courseRound);
        modelAndView.addObject("inbodyRecords", inbodyRecords);
        
        logger.info("# get inbodyRecords [{}]  ",inbodyRecords);
        List<BwhRecord> inbodyBwhs = inbodyRecordService.listBwhRecords(courseRound);
        modelAndView.addObject("inbodyBwhs", inbodyBwhs);
        
        logger.info("# get inbodyBwhs [{}]  ",inbodyBwhs);
        
        List<StudentTargetData> targetDatas = studentService.listStudentTargetData(courseRound.getStudent(), courseRound);
        modelAndView.addObject("targetDatas", targetDatas);
        
        logger.info("# get targetDatas [{}]  ",targetDatas);
        
        return modelAndView;
    }
    
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/bwh-add", method = RequestMethod.GET)
    public ModelAndView addBwh(@PathVariable("courseRoundId") Long courseRoundId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-bwh-add");
        modelAndView.addObject("pagetype", "special");
        modelAndView.addObject("courseRoundId", courseRoundId);
        
        return modelAndView;
    }
    
    @RequestMapping(value="/{courseRoundId}/bwh", method=RequestMethod.POST)
    public @ResponseBody String onEditBwh(@Secure(property = "id") Long operator,
    		                              @PathVariable("courseRoundId") Long courseRoundId,
                                          BwhRecord bwhRecord) {
        Result result = new Result();
        
        try {
            
        	CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        	Principal principal = principalService.load(Principal.class, operator);
        	
        	offlineRoundService.addBwh(bwhRecord, courseRound, principal);
            
            result.success().message("三围数据补录成功");
        } catch (Exception e) {
            
            logger.error("onEditBwh() error: " , e);
            
            result.fail().message("三围数据补录失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/edit-hours", method = RequestMethod.GET)
    public ModelAndView editHours(@PathVariable("courseRoundId") Long courseRoundId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-edit-hours");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param courseRoundId
     * @param hours
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/edit-hours", method = RequestMethod.PATCH)
    public @ResponseBody String onEditHours(@PathVariable("courseRoundId") Long courseRoundId,
                                            @RequestParam("hours") int hours) {
        Result result = new Result();
        
        try {
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            offlineRoundService.editHours(courseRound, hours);
            
            result.success().message("修改课时成功");
        } catch (BusinessException e) {
            result.fail().message(e.getMessage());
        } catch (Exception e) {
            result.fail().message("修改课时失败");
            logger.error("#onEditHours() error ", e);
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/arrange-coach", method = RequestMethod.GET)
    public ModelAndView arrangeCoach(@PathVariable("courseRoundId") Long courseRoundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-arrange-coach");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        List<Principal> coaches = coachService.listCoach(courseRound.getSite(), CourseUnit.changeTag(courseRound.getCourseUnit()));
        
        modelAndView.addObject("courseRoundId", courseRoundId);
        modelAndView.addObject("coaches", coaches);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param courseRoundId
     * @param coachId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/arrange-coach", method = RequestMethod.PATCH)
    public @ResponseBody String onArrangeCoach(@PathVariable("courseRoundId") Long courseRoundId,
                                               @RequestParam(value = "coachId") Long coachId) {
        
        Result result = new Result();
        
        try {
            
            Principal principal = principalService.load(Principal.class, coachId);
            
            // validate selected principal
            if(!principal.isCoach()) {
                
                result.fail().message("所选用户不是教练");
                
                return JsonUtils.toJsonString(result);
            }
            
            // bind coach & create schedule
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            offlineRoundService.bindIndividualCourseCoach(courseRound, principal);
            
            // init corp user ids by principal
            List<String> userids = new ArrayList<String>();
            userids.add(principal.getMobile());
            
            // TODO send crop message
            
            result.success().message("指定主教练成功");
            
        } catch (BusinessException e) {
            
            result.fail().message(e.getMessage());
            
        } catch (Exception e) {
            
            result.fail().message("指定主教练失败");
            
            logger.error("#onArrangeCoach() error ", e);
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/change-coach", method = RequestMethod.GET)
    public ModelAndView changeCoach(@PathVariable("courseRoundId") Long courseRoundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-change-coach");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        List<Principal> coaches = coachService.listCoach(courseRound.getSite(), CourseUnit.changeTag(courseRound.getCourseUnit()));
        
        modelAndView.addObject("courseRound", courseRound);
        modelAndView.addObject("coaches", coaches);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param courseRoundId
     * @param coachId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/change-coach", method = RequestMethod.PATCH)
    public @ResponseBody String onChangeCoach(@PathVariable("courseRoundId") Long courseRoundId,
                                              @RequestParam(value = "coachId") Long coachId) {
        
        Result result = new Result();
        
        try {
        
            Principal principal = principalService.load(Principal.class, coachId);
            
            // validate selected principal
            if(!principal.isCoach()) {
                result.fail().message("所选用户不是教练");
                
                return JsonUtils.toJsonString(result);
            }
            
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            
            // bind coach & create schedule
            offlineRoundService.changeIndividualCourseCoach(courseRound, principal);
            
            // init corp user ids by principal
            List<String> userids = new ArrayList<String>();
            userids.add(principal.getMobile());
            
            // TODO send crop message by status
            
            result.success().message("更改主教练成功");
            
        } catch (Exception e) {
            
            result.fail().message("更改主教练失败");
            
            logger.error("#onChangeCoach() error ", e);
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/toggle-freeze", method = RequestMethod.GET)
    public ModelAndView toggleFreeze(@PathVariable("courseRoundId") Long courseRoundId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-toggle-freeze");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/toggle-freeze", method = RequestMethod.PATCH)
    public @ResponseBody String onToggleFreeze(@PathVariable("courseRoundId") Long courseRoundId,
                                               @RequestParam(name = "holdMonth", required = false, defaultValue = "2") Integer holdMonth) {
        
        Result result = new Result();
        
        try{
            
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            
            courseRoundService.toggleFreeze(courseRound, holdMonth);
            
            result.success().message("改变状态成功");
        
        } catch(Exception e){
            
            logger.error("#onToggleFreeze - ", e);
            
            result.fail().message("改变状态失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/stop-camp", method = RequestMethod.GET)
    public ModelAndView stopCamp(@PathVariable("courseRoundId") Long courseRoundId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-stop-camp");
        modelAndView.addObject("pagetype", "special");
        modelAndView.addObject("courseRoundId", courseRoundId);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/stop-camp", method = RequestMethod.PATCH)
    public @ResponseBody String onStopCamp(@PathVariable("courseRoundId") Long courseRoundId) {
        
        Result result = new Result();
        
        try{
            
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            
            courseRoundService.stopCamp(courseRound);
            
            result.success().message("手动结营成功");
        
        } catch(Exception e){
            
            logger.error("#onStopCamp - ", e);
            
            result.fail().message("手动结营失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/delay", method = RequestMethod.GET)
    public ModelAndView delay(@Secure Login login,
                              @PathVariable("courseRoundId") Long courseRoundId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-delay");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        
        modelAndView.addObject("courseRound", courseRound);
        
        Date now = new Date();
        if(courseRound.getEffectiveEnd() == null || courseRound.getEffectiveEnd().before(now)) {
            modelAndView.addObject("effectiveEnd", DateFormatUtils.format(now, "yyyy-MM-dd HH:mm:ss"));
            modelAndView.addObject("minEffectiveEnd", DateFormatUtils.format(now, "yyyy-MM-dd HH:mm:ss"));
        } else if(login.isRoot() || login.isAdmin()) {
            modelAndView.addObject("effectiveEnd", DateFormatUtils.format(courseRound.getEffectiveEnd(), "yyyy-MM-dd HH:mm:ss"));
            modelAndView.addObject("minEffectiveEnd", DateFormatUtils.format(now, "yyyy-MM-dd HH:mm:ss"));
        } else {
            modelAndView.addObject("effectiveEnd", DateFormatUtils.format(courseRound.getEffectiveEnd(), "yyyy-MM-dd HH:mm:ss"));
            modelAndView.addObject("minEffectiveEnd", DateFormatUtils.format(courseRound.getEffectiveEnd(), "yyyy-MM-dd HH:mm:ss"));
        }
        
        return modelAndView;
    }
    
    /**
     * 
     * @param operator
     * @param courseRoundId
     * @param effectiveEnd
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/delay", method = RequestMethod.PATCH)
    public @ResponseBody String onDelay(@Secure Login login,
                                        @PathVariable("courseRoundId") Long courseRoundId,
                                        @RequestParam("effectiveEnd") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date effectiveEnd) {
        
        Result result = new Result();
        
        try{
            if(effectiveEnd.before(new Date())) {
                result.fail().message("延期失败,所选时间小于当前时间");
            } else {
                CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
                courseRoundService.delay(courseRound, effectiveEnd, login);
                
                result.success().message("延期成功");
            }
        } catch(BusinessException e) {
            result.fail().message(e.getMessage());
        } catch(Exception e){
            
            logger.error("#onDelay - ", e);
            
            result.fail().message("延期失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/activate", method = RequestMethod.GET)
    public ModelAndView activate(@PathVariable("courseRoundId") Long courseRoundId) {
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-activate");
        modelAndView.addObject("pagetype", "special");
        modelAndView.addObject("courseRoundId", courseRoundId);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/activate", method = RequestMethod.PATCH)
    public @ResponseBody String onActivate(@PathVariable("courseRoundId") Long courseRoundId) {
        
        Result result = new Result();
        
        try{
            
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            
            courseRoundService.activate(courseRound);
            
            result.success().message("激活成功");
        
        } catch(Exception e){
            
            logger.error("#onDelay - ", e);
            
            result.fail().message("激活失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/expiry-time", method = RequestMethod.GET)
    public ModelAndView editExpiryTime(@PathVariable("courseRoundId") Long courseRoundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/year/year-expiry-time");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param courseRoundId
     * @param effectiveEnd
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/expiry-time", method = RequestMethod.PATCH)
    public @ResponseBody String onEditExpiryTime(@PathVariable("courseRoundId") Long courseRoundId,
                                                 @RequestParam("effectiveEnd") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date effectiveEnd) {
        
        Result result = new Result();
        
        try {
            
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            
            courseRoundService.editExpiryTime(courseRound, effectiveEnd);
            
            result.success().message("修改过期时间成功");
            
        } catch (Exception e) {
            
            logger.error("onEditExpiryTime() error:", e);
            result.fail().message("修改过期时间失败");
        }
        
        return JsonUtils.toJsonString(result);
        
    }
    
    /**
     * view courseRoundId change group
     * 
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/change-group", method = RequestMethod.GET)
    public ModelAndView changeGroup(@PathVariable("courseRoundId") Long courseRoundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-change-group");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
        
    }
        
    /**
     * change the group
     * 
     * @param courseRoundId
     * @param coachId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/change-group", method = RequestMethod.PATCH)
    public @ResponseBody String onChangeGroup(@PathVariable("courseRoundId") Long courseRoundId,
                                              @RequestParam("groupId") Long groupId,
                                              @RequestParam(value = "tagIds", required = false) String tagIds){
        Result result = new Result();
        
        try {
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            FitnessGroup fitnessGroup = groupTemplateService.loadFitnessGroup(groupId);
            
            courseRoundService.changeGroup(courseRound, fitnessGroup, tagIds);
            
            result.success().message("更改分组成功");
            
        } catch (Exception e) {
            
            result.fail().message("更改分组失败");
            
            logger.error("#onChangeGroup() error ", e);
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param roundCode
     * @param roundId
     * @return
     */
    @RequestMapping(value = "/{roundId}/edit-group", method = RequestMethod.GET)
    public ModelAndView editGroup(@PathVariable("roundId") Long roundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-edit-group");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(roundId);
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param roundId
     * @param groupId
     * @return
     */
    @RequestMapping(value = "/{roundId}/edit-group", method = RequestMethod.PATCH)
    public @ResponseBody String onEditGroup(@PathVariable("roundId") Long roundId,
                                            @RequestParam("groupId") Long groupId){
        Result result = new Result();
        
        try {
            
            CourseRound courseRound = courseRoundService.loadCourseRound(roundId);
            FitnessGroup fitnessGroup = groupTemplateService.loadFitnessGroup(groupId);
            
            courseRoundService.editGroup(courseRound, fitnessGroup);
            
            result.success().message("更改分组成功");
            
        } catch (Exception e) {
            
            result.fail().message("更改分组失败");
            
            logger.error("#onChangeGroup() error ", e);
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param roundId
     * @return
     */
    @RequestMapping(value = "/{roundId}/edit-tag", method = RequestMethod.GET)
    public ModelAndView editTag(@PathVariable("roundId") Long roundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-tag");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(roundId);
        List<CoursewareTag> coursewareTags = persistentAccessor.coursewareTags(courseRound.getStudent().getArrayTagIds());
        List<Long> fitnessTags = new ArrayList<Long>();
        for(CoursewareTag coursewareTag : coursewareTags) {
            fitnessTags.add(coursewareTag.getFitnessTag().getId());
        }
        modelAndView.addObject("fitnessTags", fitnessTags);
        
        modelAndView.addObject("roundId", roundId);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param roundId
     * @param tagIds
     * @return
     */
    @RequestMapping(value = "/{roundId}/edit-tag", method = RequestMethod.PATCH)
    public @ResponseBody String onEditTag(@PathVariable("roundId") Long roundId,
                                          @RequestParam(value = "tagIds", required = false) String tagIds){
        Result result = new Result();
        
        try {
            CourseRound courseRound = courseRoundService.loadCourseRound(roundId);
            
            courseRoundService.editTag(courseRound, tagIds);
            
            result.success().message("添加标签成功");
            
        } catch (Exception e) {
            
            result.fail().message("添加标签失败");
            
            logger.error("#onTag() error ", e);
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/change-site", method = RequestMethod.GET)
    public ModelAndView changeSite(@PathVariable("courseRoundId") Long courseRoundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-change-site");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        List<Site> sites = siteService.list();
        List<Principal> coaches = coachService.listCoach(courseRound.getSite());
        
        modelAndView.addObject("courseRound", courseRound);
        modelAndView.addObject("sites", sites);
        modelAndView.addObject("coaches", coaches);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param courseRoundId
     * @param effectiveEnd
     * @return
     */
    @RequestMapping(value = "/{courseRoundId}/change-site", method = RequestMethod.PATCH)
    public @ResponseBody String onChangeSite(@PathVariable("courseRoundId") Long courseRoundId,
                                             @RequestParam("siteId") Long siteId,
                                             @RequestParam("coachId") Long coachId) {
        
        Result result = new Result();
        
        try {
            
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            Site site = siteService.load(siteId);
            Principal coach = principalService.load(Principal.class, coachId);
            
            courseRoundService.changeSite(courseRound, site, coach);
            
            result.success().message("转店成功");
            
        } catch (BusinessException e) {
            
            result.fail().message(e.getMessage());
            
        } catch (Exception e) {
            
            logger.error("onChangeSite() error:", e);
            result.fail().message("转店失败");
        }
        
        return JsonUtils.toJsonString(result);
        
    }

    @RequestMapping(value = "/{courseRoundId}/print", method = RequestMethod.GET)
    public ModelAndView print(@PathVariable("courseRoundId") Long courseRoundId,
                              @RequestParam("generated") boolean generated) {
        
        ModelAndView modelAndView = new ModelAndView("course/individual/individual-round-print");
        modelAndView.addObject("pagetype", "special");
        CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
        modelAndView.addObject("courseRound", courseRound);
        
        Goal goal = basicInformationService.loadGoal(courseRound);
        modelAndView.addObject("goal", goal);
        
        List<BodyDataTarget> targets = basicInformationService.listBodyDataTarget(courseRound);
        modelAndView.addObject("targets", CollectionUtils.constructMapValueFromList(targets, "bodyDataType.alias"));
        
        BasicData basicData = basicInformationService.loadBasicData(courseRound);
        modelAndView.addObject("basicData", basicData);
        
        StudentHabit habit = basicInformationService.loadStudentHabit(courseRound);
        modelAndView.addObject("habit", habit);
        
        PostureJoint postureJoint = basicInformationService.loadPostureJoint(courseRound);
        modelAndView.addObject("postureJoint", postureJoint);
        
        Map<Integer, Dietary> dietarys = groupService.listDietary(courseRound, generated);
        modelAndView.addObject("dietarys", dietarys);
        
        Map<Integer, Exercise> exercises = groupService.listExercise(courseRound, generated);
        modelAndView.addObject("exercises", exercises);
        
        Map<Integer, Map<Integer, Map<String, Object>>> schedules = groupService.listSchedule(courseRound, generated);
        modelAndView.addObject("schedules", schedules);
        
        Map<Integer, Map<String, Object>> courseCoursewares = groupService.listCourseWare(courseRound);
        modelAndView.addObject("courseCoursewares", courseCoursewares);
        
        Map<Integer, BwhRecord> bwhRecords = resultReportService.getBwhRecordMap(courseRound);
        modelAndView.addObject("bwhRecords", bwhRecords);
        
        CourseRoundResult resultReport = resultReportService.loadResultReport(courseRound);
        modelAndView.addObject("resultReport", resultReport);
        
        return modelAndView;
    }
}
